#ifndef MAP_H
#define MAP_H

#include <QSet>
#include <QVector3D>

#include "ai/path.h"
#include "geometry/edge3d.h"
#include "geometry/quadtree.h"
#include "global/typedef.h"
#include "object/face.h"
#include "object/object.h"
#include "object/paintable.h"

class QString;

class Map : public Paintable
{
public:
    Map();
    ~Map();

    bool isValid() const;

    const Object& object() const; // TODO : CACA !

    const Quadtree< Edge3D >& walls() const;
    const Quadtree< Face >& walkables() const;

    bool load(const QString& rkFileName);
    void paint() const;

    QVector3D snap(const QVector3D& rkPosition) const;
    Path findPath(const QVector3D& rkStart, const QVector3D& rkEnd) const;

protected:
    Map(const Map&);
    Map& operator = (const Map&);

private:
    static bool hover(const QVector3D& rkVertex, const Face& rkFace);

    const Face* findAt(const QVector3D& rkPosition) const;
    void connect(const QVector3D& rkStart, const Face& rkStartFace,
                 const QVector3D& rkEnd, const Face& rkEndFace) const;
    void disconnect() const;
    Path& smooth(Path& rkPath) const;

    //------------------------------------------------
    //  Attributes.
    //------------------------------------------------
    // State.
    bool                         m_bIsValid;

    // Spatial representation.
    Object                       m_kMapObject;

    // Navigation graph.
    mutable Graph                m_kGraph;
    QSet< const Edge3D >         m_kGates;
    QSet< const Edge3D >         m_kWalls;
    mutable QSet< const Edge3D > m_kExtras;

    // Spatial organization.
    Quadtree< Edge3D >           m_kQuadtreeWalls;
    Quadtree< Edge3D >           m_kQuadtreeGates;
    Quadtree< Face >             m_kQuadtreeWalkables;
};

#endif // MAP_H
